const uuid = require("uuid");
const axios = require("axios").default.create({
  headers: {
    "User-Agent": "okhttp/3.10.0"
  }
});
const util = require("util");
const path = require("path");
const fs = require("fs");
const buffer = require("buffer");
const url = require("url");
const crypto = require("crypto");
const qs = require("querystring")
const FormData = require("form-data");
const randomstring = require("randomstring");
const random_number = require("random-number");
const rannum = random_number;
// const uuid = require("uuid");
const randomcolor = require("randomcolor");
const JsB64 = require("js-base64").Base64;
const runParallel = require("run-parallel-limit");
const LibOwhat = require("lib-owhat/lib/v0.0.1/");
const LibMeipian = require("upload-meipian/lib").WebWrapper;
const Toolbox = require("./Toolbox");
const CommonAxerrHandlerGen = require("./CommonAxerrHandler");
const HiaitaLogin = require("./simple_login/hiaita_inyota");
const BabyTreeLogin = require("./simple_login/babytree");
const $Dú = require("./simple_login/du_app")
const Soyoung = require("./simple_login/soyoung");


class TokenGetter {
  /**
   * @returns {Promise<{ok:Boolean,msg:String,data:{uptoken:String,key:string} }>}
   * @param {String} ext_name 
   */
  static get_daovoice(ext_name = ".gif") {
    /**
  * @returns {Object}
  * @param {String} response_luanma 
  */
    function parseDaoVoiceResponse(response_luanma) {
      function o(e) {
        for (var t = "", a = 0; a < e.length; a++)
          t += String.fromCharCode(7 ^ e.charCodeAt(a));
        return t
      }
      let t = o(response_luanma)
      return JSON.parse(t);
    }
    let filename = uuid() + ext_name;
    return new Promise(resolve => {
      axios.post(`https://im.daovoice.io/v1/upload-token`, {
        app_id: "58b13efb",
        people: {
          anonymous_id: uuid()
        },
        uploads: {
          name: filename,
          content_type: "image/gif" || "application/octet-stream"
        }
      }, {
          validateStatus: s => s == 200
        }).then(axresp => {
          if (axresp.headers['content-type'] && axresp.headers['content-type'].includes("text/plain")) {
            try {
              let body = parseDaoVoiceResponse(axresp.data);
              if (!(body['qiniu_token'] && body['upload_path'])) {
                return resolve({
                  ok: false,
                  msg: `不合预期:${util.inspect(body)}`
                })
              }
              let qiniu_token = body['qiniu_token'];
              let upload_path = body['upload_path'];
              resolve({
                ok: true,
                msg: "ok",
                data: {
                  uptoken: qiniu_token,
                  key: upload_path
                }
              })
            } catch (json_err) {
              return CommonAxerrHandlerGen(`error when parseDaoVoiceResponse(乱码):${util.inspect(json_err)}`)
            }
          } else {
            throw new Error(`axresp.headers['content-type'] is ${axresp.headers['content-type']},` +
              `and the response body is ${axresp.data}`)
          }
        }).catch(axerr => {
          CommonAxerrHandlerGen(resolve)(axerr);
        })
    })
  }

  /**
  * @returns {Promise<{ok:Boolean,msg:String,data:{uptoken:String} }>}
  */
  static get_7moor() {
    return new Promise(resolve => {
      axios.get('http://webchat.7moor.com/chat?data={%22action%22:%22qiniu.getUptokenFromCustomer%22}', {
        headers: {
          'Content-Type': "application/x-www-form-urlencoded; charset=UTF-8",
          Referer: "http://webchat.7moor.com/view/moor_chat.html", //"http://webchat.7moor.com/view/moor_chat.html?v=20180427"
          "X-Requested-With": "XMLHttpRequest",
          "User-Agent": "Mozilla/5.0 (iPad; CPU OS 9_3_5 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13G36 Safari/601.1"
        },
        validateStatus: s => s == 200
      }).then(axresp => {
        if (axresp.data && axresp.data.uptoken) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              uptoken: axresp.data.uptoken
            }
          })
        }
        throw new Error(`不合预期的响应:${util.inspect(axresp.data)}`);
      }).catch(axerr => {
        CommonAxerrHandlerGen(resolve)(axerr)
      })
    })
  }

  /**
  * @returns {Promise<{ok:Boolean,msg:String,data:{uptoken:String,key:String} }>}
  */
  static get_tuniu() {
    return new Promise(resolve => {
      let as_gif_name = `${uuid()}.gif`
      axios.get(`https://api.tuniu.com/image/upload/token/new`, {
        params: {
          c: JSON.stringify({
            cc: parseInt(random_number({ min: 2500, max: 2510 })),
            ct: parseInt(random_number({ min: 20, max: 25 })),
            dt: 1,
            ov: 20,
            p: parseInt(random_number({ min: 10423, max: 10598 })),
            v: "10.9.0"
          }),
          d: JSON.stringify({
            fileName: `qn/image/${as_gif_name}`,
            userId: parseInt(random_number({ min: 82618211 - 20, max: 82618211 + 10 }))
          })
        },
        headers: {
          "User-Agent": "TuNiuApp/10.9.0 (Android)",
          sessionid: 'cf8bb25f82c66f153c22b460cf72728a_',
          sid: uuid()
        },
        validateStatus: s => s == 200
      }).then(axresp => {
        // debugger
        if (axresp.data && axresp.data.success
          && axresp.data.data
          && axresp.data.data.token
          && axresp.data.data.fileName) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              uptoken: axresp.data.data.token,
              key: axresp.data.data.fileName
            }
          })
        }
        throw new Error(`NOT sanity resp:${util.inspect(axresp.data)}`)
      }).catch(axerr => {
        CommonAxerrHandlerGen(resolve)(axerr);
      })
    })
  }

  /**
  * @returns {Promise<{ok:Boolean,msg:String,data:{uptoken:String} }>}
  */
  static get_udesk() {
    return new Promise(resolve => {
      axios.get('http://bdkj.udesk.cn/spa1/file_upload_policy', {
        params: {
          marking: "client.chat_upload",
          key: `${randomstring.generate(5)}.jpg`,
          "access_token": uuid()
        },
        validateStatus: s => s == 200,
        timeout: 5000
      }).then(axresp => {
        if (axresp.data && axresp.data['token']) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              uptoken: axresp.data['token']
            }
          })
        }
        throw new Error(`不合预期的响应:${util.inspect(axresp.data)}`);
      }).catch(axerr => {
        CommonAxerrHandlerGen(resolve)(axerr);
      })
    })
  }

  /**
  * @returns {Promise<{ok:Boolean,msg:String,data:{uptoken:String} }>}
  */
  static get_soyoung() {
    return new Promise(async resolve => {
      let o_token = await Soyoung.getQiniuToken();
      if (!o_token.ok) {
        return resolve({
          ok: false,
          msg: o_token.msg
        })
      } else {
        return resolve({
          ok: true,
          msg: "ok",
          data: {
            uptoken: o_token.data.uptoken
          }
        })
      }
    })
  }

  /**
  * @returns {Promise<{ok:Boolean,msg:String,data:{uptoken:String} }>}
  */
  static get_dú() {
    return $Dú.get_token();
  }

  /**
* @returns {Promise<{ok:Boolean,msg:String,data:{uptoken:String} }>}
*/
  static get_hunliji() {
    return new Promise(resolve => {
      axios.get('https://www.hunliji.com/p/wedding/home/APIUtils/image_upload_token', {
        headers: {
          'Content-Type': "application/x-www-form-urlencoded; charset=UTF-8",
          "user-agent": "okhttp/3.10.0",
          'devicekind': 'android',
          'phone': uuid()
        },
        validateStatus: s => s == 200
      }).then(axresp => {
        // debugger
        if (axresp.data && axresp.data.uptoken) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              uptoken: axresp.data.uptoken
            }
          })
        }
        throw new Error(`不合预期的响应:${util.inspect(axresp.data)}`);
      }).catch(axerr => {
        CommonAxerrHandlerGen(resolve)(axerr)
      })
    })
  }

  /**
   * @returns {Promise<{ok:boolean,msg:String,data:{uptoken:String,key:String}}>}
   * @param {String} ext_name 
   */
  static get_pianke(ext_name = "bin") {
    function getTimeString() {
      let d = new Date;
      let month = d.getMonth() + 1;
      if (month < 10) {
        month = '0' + month;
      }
      let dayOfMonth = d.getDate();
      if (dayOfMonth < 10) {
        dayOfMonth = '0' + dayOfMonth;
      }
      let hour = d.getHours();
      if (hour < 10) hour = '0' + hour;
      let minute = d.getMinutes();
      if (minute < 10) minute = '0' + minute;
      let second = d.getSeconds();
      if (second < 10) second = '0' + second;
      /** @todo*/
      return `${d.getFullYear()}${month}${dayOfMonth}${hour}${
        minute
        }${second}`
    };
    function getSig(timestamp) {
      return crypto.createHash("md5").update(`4762000` + "" + timestamp).digest("hex").toUpperCase();
    };
    return new Promise(resolve => {
      let timestamp = getTimeString();
      axios.post(`http://pianke.me/version5.0/additional/getQNUploadToken.php?sig=${getSig(timestamp)}`,
        qs.stringify({ filetype: ext_name }),
        {
          headers: {
            "User-Agent": `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/5${rannum({ min: 25, max: 37 })}.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36`,
            Referer: "http://pianke.me/editor/",
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
            "X-Requested-With": "XMLHttpRequest",
            Authorization: `4762000:${timestamp}`.toBase64(true) //这里前面的userid居然可以假装别人的哈哈哈哈
          },
          validateStatus: s => s == 200
        }
      ).then(axresp => {
        if (axresp.data && axresp.data['data'] && axresp.data['data']['token'] && axresp.data['data']['filename']) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              uptoken: axresp.data['data']['token'],
              key: axresp.data['data']['filename']
            }
          })
        }
        throw new Error(`不合预期的响应:${util.inspect(axresp.data)}`)
      }).catch(axerr => {
        CommonAxerrHandlerGen(resolve)(axerr);
      })
    })
  }

  /**
   * @returns {Promise}
   * @param {Number} time ms
   */
  static pause_promise_gen(time = 1000) {
    time = parseInt(time);
    if (time < 10) {
      time = 10
    }
    return new Promise(r => {
      setTimeout(r, time)
    })
  }

  /**
  * @returns {Promise<{ok:Boolean,msg:String,data:{uptoken:String} }>}
  */
  static get_meipian() {
    return new Promise(async resolve => {
      let o_ins = await LibMeipian.getGoodInstance();
      if (!o_ins.ok) {
        return resolve({
          ok: false,
          msg: `failed to get meipian instance:${o_ins.msg}`
        })
      }
      let o_token = await o_ins.instance.getUpToken();
      if (!o_token.ok) {
        return resolve({
          ok: false,
          msg: `failed to get meipian token:${o_token.msg}`
        })
      }
      resolve({
        ok: true,
        msg: "ok",
        data: {
          uptoken: o_token.data.uptoken
        }
      })
    })
  }

  /**
   * @description {"callbackUrl":"http:\\/\\/app.hiaita.com\\/core\\/attachment\\/attachment\\/qiNiuCallback","callbackHost":"app.hiaita.com","callbackBody":"{\\"key\\": \\"$(key)\\", \\"hash\\": \\"$(etag)\\", \\"w\\": $(imageInfo.width), \\"h\\": $(imageInfo.height), \\"size\\": $(fsize)}","scope":"aitaapp","deadline":1551280703}
  * @returns {Promise<{ok:Boolean,msg:String,data:{uptoken:String} }>}
  */
  static get_hiaita() {
    return new Promise(async resolve => {
      let o_token = await HiaitaLogin.get_token();
      resolve(o_token);
    })
  }

  /**
  * @returns {Promise<{ok:Boolean,msg:String,data:{uptoken:String,key:string} }>}
  */
  static get_owhat() {
    return new Promise(async resolve => {
      let o_ins = await LibOwhat.OwhatWrapper.getValidInstance("hujimiya@yandex.by", "owhat65huji");
      if (!o_ins.ok) {
        return resolve({
          ok: false,
          msg: `login fail:${o_ins.msg}`
        })
      }
      let o_token = await o_ins.instance.__getUploadToken();
      if (!o_token.ok) {
        return resolve({
          ok: false,
          msg: o_token.msg
        })
      }
      return resolve({
        ok: true,
        msg: "ok",
        data: {
          uptoken: o_token.data.token,
          key: o_token.data.key
        }
      })
    })
  }


  /**
  * @returns {Promise<{ok:Boolean,msg:String,data:{uptoken:String} }>}
  */
  static get_babytree() {
    return new Promise(async resolve => {
      let o_token = await BabyTreeLogin.getToken();
      resolve({
        ok: o_token.ok,
        msg: o_token.msg,
        data: {
          uptoken: o_token.ok ? o_token.data.uptoken : ""
        }
      })
    })
  }

  /**
  * @returns {Promise<{ok:Boolean,msg:String,data:{uptoken:String} }>}
  */
  static get_any() {
    return new Promise(async resolve => {
      /**@type {Array<string>} */
      let errs = [];
      for (let i = 1; i <= 4; i++) {
        let o_tryOwhat = await this.get_owhat();
        if (o_tryOwhat.ok) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              uptoken: o_tryOwhat.data.uptoken
            }
          })
        } else {
          errs.push(`failed to get owhat token:${o_tryOwhat.msg}`);
          await this.pause_promise_gen(i * 1000);
        }
      }
      for (let i = 1; i <= 4; i++) {
        let o_tryHunliji = await this.get_hunliji();
        if (o_tryHunliji.ok) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              uptoken: o_tryHunliji.data.uptoken
            }
          })
        } else {
          errs.push(`failed to get hunliji token:${o_tryHunliji.msg}`);
          await this.pause_promise_gen(i * 1000);
        }
      }
      for (let i = 1; i <= 4; i++) {
        let o_try7moor = await this.get_7moor();
        if (o_try7moor.ok) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              uptoken: o_try7moor.data.uptoken
            }
          })
        } else {
          errs.push(`failed to get 7moor token:${o_try7moor.msg}`);
          await this.pause_promise_gen(1 * 1000);
        }
      }

      for (let i = 1; i <= 4; i++) {
        let o_tryTuniu = await this.get_tuniu();
        if (o_tryTuniu.ok) {
          return resolve({
            msg: "ok",
            data: {
              uptoken: o_tryTuniu.data.uptoken
            },
            ok: true
          })
        } else {
          errs.push(`failed to get tuniu token:${o_tryTuniu.msg}`);
          await this.pause_promise_gen(500);
        }

      }

      errs.unshift(`failed try hunliji ,7moor and tuniu get token:`)
      return resolve({
        ok: false,
        msg: errs.join("  \n  ")
      })
    })
  }
}

module.exports = {
  TokenGetter: TokenGetter
}